/*
日志输出插件
初始化指定输出方法（int）: SCREEN 0 ONE_FILE 1 CLASS_FILE 2 支持 |
         输出路径（string）：默认 ./Log/
使用直接（int level "message"）
level:DEBUG INFO  WARING ERROR FATAL
*/
#pragma once
#include <cstdio>

#include<unistd.h>
#include<string>
#include <cstdarg>
#include<ctime>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<sstream>
using namespace std;

#define FORMAT "::"
#define SIZE 1024
#define MODE 0666

#define SCREEN     1
#define ONE_FILE   2
#define CLASS_FILE 4 


enum Message{
    DEBUG,
    INFO,
    WARNING,
    ERROR,
    FATAL
};

class Log
{
public:
    Log(int method=SCREEN,string Dirth="./Log/")
    {
        _method=method;
        _DirPath=Dirth;
    }
    //重载（）
    void operator()(int level,const char * format,...)
    {
        //时间处理
        tm *datetime;
        time_t t=time(NULL);
        datetime=localtime(&t);
        
        //日志等级处理
        string slevel=getLevel(level);

        //日志信息处理
        va_list s;
        va_start(s,format);
            //日志常规信息
        char InfoMessage[SIZE];
        snprintf(InfoMessage,sizeof(InfoMessage),"[%s][%d-%d-%d %d:%.2d:%d]",slevel.c_str(),datetime->tm_year+1900,datetime->tm_mon,datetime->tm_mday,
        datetime->tm_hour,datetime->tm_min,datetime->tm_sec);
            //日志内容
        char Message[SIZE];
        vsnprintf(Message,sizeof(Message), format,s);        
        va_end(s);
        
        


        // char TotalMessage[2*SIZE];
        ostringstream oss;
        oss<<InfoMessage<<":"<<Message;
        // snprintf(TotalMessage,sizeof(TotalMessage),"%s:%s\n",InfoMessage,Message);
        //输出日志
        PrintMessage(oss.str().c_str(),level);
        
    }
    string getLevel(int level)
    {
        switch (level) {
            case DEBUG:
                return "DEBUG";
            break;
            case INFO:
                return "INFO";
            break;
            case WARNING:
                return "WARNING";
            break;
            case FATAL:
                return "FATAL";
            break;
            case ERROR:
                return "ERROR";
            break;
        }
        return "";
    }
    void PrintFile(string &message,string &path)
    {
        int fd=open(path.c_str(),O_APPEND|O_CREAT|O_WRONLY,MODE);
        write(fd,message.c_str(), message.length());
        close(fd);
    }
    void PrintMessage(const char* TotalMessage,int level)
    {
        string message=TotalMessage;
        if((_method&SCREEN))
        {
            printf("%s",message.c_str());
            fflush(stdout);
            
        }
        if((_method&ONE_FILE))
        {
            string path=_DirPath+"log.txt";
            PrintFile(message,path);
        }
        if((_method&CLASS_FILE))
        {
            string mode=getLevel(level);
            string path=_DirPath+"log.";
            path+=mode+".txt";
            PrintFile(message,path);
        }
    }
    ~Log()
    {
    }
private:
    int _method;
    std::string _DirPath;
};